package com.example.rabbitmq.starter.dao;

import com.example.rabbitmq.starter.entity.FailedMessageInfo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * 失败消息信息数据访问接口
 */
@Transactional
@Repository
public interface FailedMessageRepository extends JpaRepository<FailedMessageInfo, String> {
    
    /**
     * 根据消息ID查询失败消息信息
     *
     * @param messageId 消息ID
     * @return 失败消息信息
     */
    FailedMessageInfo findByMessageId(String messageId);
    
    /**
     * 根据业务ID查询失败消息信息
     *
     * @param businessId 业务ID
     * @return 失败消息信息列表
     */
    List<FailedMessageInfo> findByBusinessId(String businessId);
    
    /**
     * 根据业务ID分页查询失败消息信息
     *
     * @param businessId 业务ID
     * @param pageable 分页参数
     * @return 分页的失败消息信息
     */
    Page<FailedMessageInfo> findByBusinessId(String businessId, Pageable pageable);
    
    /**
     * 根据消息类型查询失败消息信息
     *
     * @param messageType 消息类型
     * @return 失败消息信息列表
     */
    List<FailedMessageInfo> findByMessageType(String messageType);
    
    /**
     * 根据业务ID和消息类型查询失败消息信息
     *
     * @param businessId 业务ID
     * @param messageType 消息类型
     * @return 失败消息信息列表
     */
    List<FailedMessageInfo> findByBusinessIdAndMessageType(String businessId, String messageType);
    
    /**
     * 根据状态查询失败消息信息
     *
     * @param status 状态
     * @return 失败消息信息列表
     */
    List<FailedMessageInfo> findByStatus(String status);
    
    /**
     * 根据消息类型和状态查询失败消息信息
     *
     * @param messageType 消息类型
     * @param status 状态
     * @return 失败消息信息列表
     */
    List<FailedMessageInfo> findByMessageTypeAndStatus(String messageType, String status);
    
    /**
     * 根据消息类型分页查询失败消息信息
     *
     * @param messageType 消息类型
     * @param pageable 分页参数
     * @return 分页的失败消息信息
     */
    Page<FailedMessageInfo> findByMessageType(String messageType, Pageable pageable);
    
    /**
     * 根据状态分页查询失败消息信息
     *
     * @param status 状态
     * @param pageable 分页参数
     * @return 分页的失败消息信息
     */
    Page<FailedMessageInfo> findByStatus(String status, Pageable pageable);
    
    /**
     * 根据消息类型和状态分页查询失败消息信息
     *
     * @param messageType 消息类型
     * @param status 状态
     * @param pageable 分页参数
     * @return 分页的失败消息信息
     */
    Page<FailedMessageInfo> findByMessageTypeAndStatus(String messageType, String status, Pageable pageable);
    
    /**
     * 查询指定时间范围内的失败消息
     *
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 失败消息信息列表
     */
    List<FailedMessageInfo> findByFailTimeBetween(Date startTime, Date endTime);
    
    /**
     * 更新失败消息状态
     *
     * @param id 失败消息ID
     * @param status 新状态
     * @param processResult 处理结果
     * @param lastRetryTime 最后重试时间
     * @return 更新的记录数
     */
    @Modifying
    @Query("UPDATE FailedMessageInfo f SET f.status = :status, f.processResult = :processResult, f.lastRetryTime = :lastRetryTime WHERE f.id = :id")
    int updateStatus(@Param("id") String id, @Param("status") String status, 
                    @Param("processResult") String processResult, @Param("lastRetryTime") Date lastRetryTime);
    
    /**
     * 增加重试次数
     *
     * @param id 失败消息ID
     * @param lastRetryTime 最后重试时间
     * @return 更新的记录数
     */
    @Modifying
    @Query("UPDATE FailedMessageInfo f SET f.retryCount = f.retryCount + 1, f.lastRetryTime = :lastRetryTime WHERE f.id = :id")
    int incrementRetryCount(@Param("id") String id, @Param("lastRetryTime") Date lastRetryTime);
}